package com.etone.smartAudit.utils;

import com.etone.smartAudit.vo.FileVO;
import com.etone.smartAudit.vo.auditException.AuditExceptionByteArrayOutputStream;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author: 蒋学伟
 * @create: 2020-07-06 19:17:58
 * @Description ZipUtil
 */
@Component
public class ZipUtil {

    private static final int BUFFER_SIZE = 1024 * 4;

    public static String filePath;

    @Value("${audit.filePath}")
    public void setDefaultFilePath(String defaultFilePath) {
        ZipUtil.filePath = defaultFilePath;
    }

    /**
     * 压缩文件
     *
     * @param files
     * @param zipFile
     */
    public static void toZip(List<File> files, File zipFile) {
        ZipOutputStream zos = null;
        FileOutputStream out = null;
        try {
            out = new FileOutputStream(zipFile);
            zos = new ZipOutputStream(out);
            for (File file : files) {
                byte[] buf = new byte[BUFFER_SIZE];
                ZipEntry zipEntry = new ZipEntry("o" + file.getName());
                zos.putNextEntry(zipEntry);
                int len;
                FileInputStream in = new FileInputStream(file);
                while ((len = in.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                zos.setComment("我是注释");
                zos.closeEntry();
                in.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (zos != null) {
                    zos.close();
                }
                if (out != null) {
                    out.close();
                }
            } catch (IOException ioe) {
                ioe.printStackTrace();
            }
        }
    }

    /**
     * 下载zip文件
     *
     * @param fileVOS
     * @param fileName
     * @param response
     */
    public static void downloadFileZip(List<FileVO> fileVOS, String fileName, HttpServletResponse response) {
        ZipOutputStream zipOutputStream = null;
        try {
            zipOutputStream = new ZipOutputStream(response.getOutputStream());
            filePathToZipStream(fileVOS, response.getOutputStream());
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            //让浏览器下载文件,name是上述默认文件下载名
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.flushBuffer();
        } catch (Exception e) {

        } finally {
            if (zipOutputStream != null) {
                try {
                    zipOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 将io流写入到zip中
     *
     * @param fileVOS
     * @param outputStream
     */
    public static ZipOutputStream filePathToZipStream(List<FileVO> fileVOS, OutputStream outputStream) {
        if (fileVOS == null) {
            return null;
        }
        ZipOutputStream zos = null;
        try {
            zos = new ZipOutputStream(outputStream);
            for (int i = 0; i < fileVOS.size(); i++) {

                FileVO fileVO = fileVOS.get(i);
                File file = new File(filePath + "/" + fileVO.getUrl());
                byte[] buf = new byte[BUFFER_SIZE];
                ZipEntry zipEntry = new ZipEntry(fileVO.getOriginName());
                zos.putNextEntry(zipEntry);
                int len;
                FileInputStream in = new FileInputStream(file);
                while ((len = in.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                in.close();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        return zos;
    }

    /**
     * 将io流写入到zip中
     *
     * @param outputStreams
     * @param fileName
     * @param response
     */
    public static void ioToZip(List<AuditExceptionByteArrayOutputStream> outputStreams, String fileName, HttpServletResponse response) {
        if (outputStreams == null) {
            return;
        }
        ZipOutputStream zos = null;
        try {
            zos = ioMergeZip(response.getOutputStream(),outputStreams,fileName);
            //response.reset();
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            //让浏览器下载文件,name是上述默认文件下载名
            response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
            response.flushBuffer();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (zos != null) {
                    zos.close();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }

    /**
     * 将io流转文件
     *
     * @param outputStreams
     * @param fileName
     */
    public static MultipartFile ioTOMultipartFile(List<AuditExceptionByteArrayOutputStream> outputStreams, String fileName) {
        if (outputStreams == null) {
            return null;
        }
        ZipOutputStream zos = null;
        try {
            FileItemFactory factory = new DiskFileItemFactory();
            FileItem item = factory.createItem(fileName, "text/plain", true, fileName);
            zos = ioMergeZip(item.getOutputStream(), outputStreams, fileName);
            return new CommonsMultipartFile(item);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (zos != null) {
                    zos.close();
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return null;
    }

    public static ZipOutputStream ioMergeZip(OutputStream outputStream, List<AuditExceptionByteArrayOutputStream> outputStreams, String fileName) {
        ZipOutputStream zos = new ZipOutputStream(outputStream);
        try {
            for (int i = 0; i < outputStreams.size(); i++) {
                AuditExceptionByteArrayOutputStream arrayOutputStream = outputStreams.get(i);
                byte[] buf = new byte[BUFFER_SIZE];
                ZipEntry zipEntry = new ZipEntry(arrayOutputStream.getFileName());
                zos.putNextEntry(zipEntry);
                int len;
                ByteArrayInputStream in = new ByteArrayInputStream(arrayOutputStream.toByteArray());
                BufferedInputStream bis = new BufferedInputStream(in);
                while ((len = bis.read(buf)) != -1) {
                    zos.write(buf, 0, len);
                }
                zos.closeEntry();
                in.close();
                bis.close();
                arrayOutputStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return zos;
    }
}
